package com.dji.ux.sample.VirtualSticks.Panorama;

import android.content.Context;
import android.util.Log;

import androidx.annotation.Nullable;

import com.dji.ux.sample.DJISampleApplication;
import com.dji.ux.sample.ModuleVerificationUtil;
import com.dji.ux.sample.Utils.GimbalUtil;

import java.util.Timer;
import java.util.TimerTask;

import dji.common.camera.SettingsDefinitions;
import dji.common.flightcontroller.virtualstick.FlightCoordinateSystem;
import dji.common.flightcontroller.virtualstick.VerticalControlMode;
import dji.common.flightcontroller.virtualstick.YawControlMode;
import dji.keysdk.DJIKey;
import dji.keysdk.FlightControllerKey;
import dji.keysdk.callback.KeyListener;
import dji.sdk.camera.Camera;
import dji.sdk.flightcontroller.FlightController;
import dji.sdk.sdkmanager.DJISDKManager;

import static com.dji.ux.sample.Utils.SimpleUtils.showToast;
import static java.lang.Thread.sleep;

/**
 * @description： 摇杆全景拍摄控制器，由两个任务计时器组成：
 * <p>
 * 1.虚拟摇杆数据发送计时器：间隔250ms给无人机发送一次虚拟摇杆数据，控制无人机旋转到指定heading进行拍摄
 * 2.无人机角度检测器：间隔5秒检测一次无人机heading，若当前heading与目标heading相差小于2°则进行拍照
 * @author： HaolinLv
 * @time： 2022/1/3 20:09
 */
public class VirtualStickPanoramaController {

    private String TAG = this.getClass().getName();
    //大疆相机对象
    private Camera camera;
    //主activity的context对象
    private Context mcontext;
    //无人机实时heading(值域：-180~180度)
    private float curHeading;
    //无人机飞控对象
    private FlightController mflightController;
    //虚拟遥控任务计时器,模拟遥控器间隔250ms发送一次摇杆控制信号
    private Timer mSendVirtualStickDataTimer;
    //虚拟遥控任务实例
    private VirtualStickPanoramaTask mVirtualStickPanoramaTask;
    //拍摄图片计数
    private int picCount;
    //拍摄的目标heading列表
    //在0°(正北方向)拍摄垂直向下以及水平向前两张照片
    //90°(东方向)、180°(南方向)、-90°(西方向)拍摄水平向前的照片共三张
    private float[] headingList = {0, 0, 90, 180, -90};
    //目标heading变量
    private float targetHeading;

    /**
     * 摇杆全景实例对象
     *
     * @param context
     * @param flightController
     */

    public VirtualStickPanoramaController(Context context, FlightController flightController) {

        mcontext = context;
        mflightController = flightController;
        mVirtualStickPanoramaTask = new VirtualStickPanoramaTask(flightController);
        mSendVirtualStickDataTimer = new Timer();
        GimbalUtil.adjustGimbalPitch(-90);

        if (ModuleVerificationUtil.isCameraModuleAvailable()) {
            //修改摄像头拍摄模式为SINGLE
            camera = DJISampleApplication.getProductInstance().getCamera();
            camera.setMode(SettingsDefinitions.CameraMode.SHOOT_PHOTO, djiError -> {
            });
            camera.setShootPhotoMode(SettingsDefinitions.ShootPhotoMode.SINGLE, djiError -> {
            });
        }

        //无人机heading监听器
        DJIKey compassKey = FlightControllerKey.create(FlightControllerKey.COMPASS_HEADING);
        DJISDKManager.getInstance().getKeyManager().addListener(compassKey, new KeyListener() {
            @Override
            public void onValueChange(@Nullable Object oldvalue, @Nullable Object newvalue) {
                //返回更新前以及更新后的heading，当无人机heading改变的时候会触发此method(用手拿起无人机旋转也会触发)
                curHeading = (float) newvalue;
                Log.d(TAG, oldvalue + "onCOMPASS_HEADINGChange: " + newvalue + newvalue.getClass());
            }
        });

    }

    /**
     * 开始执行摇杆全景任务，点击“摇杆全景”按钮触发此method
     */
    public void shootPanorama() {

        if (mflightController != null) {
            //更改虚拟摇杆控制方式如下
            mflightController.setRollPitchCoordinateSystem(FlightCoordinateSystem.GROUND);
            mflightController.setVerticalControlMode(VerticalControlMode.VELOCITY);
            mflightController.setYawControlMode(YawControlMode.ANGLE);
            mflightController.setVirtualStickAdvancedModeEnabled(true);
            mflightController.setVirtualStickModeEnabled(true, djiError -> {
                if (djiError != null) showToast(mcontext, djiError.getDescription());
                    //执行虚拟摇杆数据发送的计时任务
                else mSendVirtualStickDataTimer.schedule(mVirtualStickPanoramaTask, 100, 250);
            });
            picCount = 0;
            //执行无人机角度检测计时任务
            Timer timer = new Timer();
            TimerTask timerTask = new TimerTask() {
                @Override
                public void run() {
                    Log.d(TAG, "VirtualStickPanoramaController{" +
                            "curHeading=" + curHeading +
                            ", picCount=" + picCount +
                            ", targetHeading=" + targetHeading +
                            '}');
                    //检测当前heading与目标heading相差值，相差小于2度则开始拍照
                    if (Math.abs(curHeading - targetHeading) < 2) {
                        shootPhoto();
                        //完成拍照后更新拍照数
                        picCount++;
                        if (picCount > 4) {
                            //完成任务后恢复虚拟摇杆相关设置
                            timer.cancel();
                            mflightController.setVirtualStickModeEnabled(false, djiError -> {
                            });
                            mflightController.setRollPitchCoordinateSystem(FlightCoordinateSystem.BODY);
                            mflightController.setYawControlMode(YawControlMode.ANGULAR_VELOCITY);
                        } else {
                            if (picCount == 1) {
                                //拍完第一张后把云台pitch重置为0°
                                GimbalUtil.adjustGimbalPitch(-50);
                            }
                            //更新目标heading
                            try {
                                sleep(1000);
                            } catch (InterruptedException e) {
                                e.printStackTrace();
                            }
                            targetHeading = headingList[picCount];
                            //修改虚拟遥控任务实例发送的Yaw值，控制无人机旋转到下一个目标heading
                            mVirtualStickPanoramaTask.mYaw = targetHeading;
                        }
                    }
                }
            };
            timer.schedule(timerTask, 3000, 5000);
        }
    }

    /**
     * 调用相机进行拍摄
     */
    private void shootPhoto() {
        if (ModuleVerificationUtil.isCameraModuleAvailable()) {
            camera.startShootPhoto(djiError -> {
                if (djiError != null) showToast(mcontext, djiError.getDescription());
            });
        }
    }

}
